/***************************************************************************
 *   Copyright (C) 2007 by Alexandre Masselot,,,   *
 *   alex@alex-laptop   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Library General Public License as       *
 *   published by the Free Software Foundation; either version 2 of the    *
 *   License, or (at your option) any later version.                       *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this program; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include <limits.h>
#include "peak.h"

namespace bol {
  boost::regex *Peak::s_pattern_charges=NULL;
  boost::cmatch *Peak::s_matches_charges=NULL;

  ostream& operator<<(ostream& out, const Peak& p){
    return out<<p.moz()<<"\t"<<Peak::chargemask2string(p.chargemask());
  }
  ostream& operator<<(ostream& out, const Peak* p){
    return out<< *p;
  }


  void Peak::buildChargesList(){
    int n=0;
    for (unsigned int i=1; i<sizeof(Pchargemask)*8; i++){
      if ((((Pchargemask)1)<<i) & m_chargemask){
        n++;
      }
    }
    m_charges=new unsigned int[n+1];
    m_charges[n]=0;
    n=0;
    for (unsigned int i=1; i<sizeof(Pchargemask)*8; i++){
      if ((((Pchargemask)1)<<i) & m_chargemask){
        m_charges[n++]=i;
      }
    }
  }


  string Peak::chargemask2string(const Pchargemask mask){
    if(mask==0)return "?";
    string s="";
    bool comma=false;
    for (unsigned int i=1; i<sizeof(Pchargemask)*CHAR_BIT; i++){
      if ((((Pchargemask)1)<<i)&mask){
        if(comma)
          s+=",";
        comma=true;
        s+=boost::lexical_cast<string>(i);
      }
    }
    return s;
  }
  Pchargemask Peak::string2chargemask(const string& s){
    if(s=="?")
      return 0;
    if(!s_pattern_charges){
      s_pattern_charges=new boost::regex();
      s_pattern_charges->assign("\\d+",boost::regex_constants::icase|boost::regex_constants::perl);
      s_matches_charges=new boost::cmatch();
    }
    const char *begin=s.c_str();
    const char *end=begin+s.length();
    Pchargemask mask=0;
      //while (boost::regex_match(bla.begin(), matches, re))
    while (boost::regex_search(begin, end, *s_matches_charges, *s_pattern_charges))
    {
      string s_onecharge((*s_matches_charges)[0].first, (*s_matches_charges)[0].second);
      int onecharge=boost::lexical_cast<int>(s_onecharge);
         ///@todo see how we can make the check that onecharge is within 1..sizeof(unsigned long int)
         // Yak says: works with "sizeof(unsigned long int)*CHAR_BIT" using CHAR_BIT found in "limits.h"
      mask|= (((Pchargemask)1)<<onecharge);
      begin = (*s_matches_charges)[0].second;
    }
    return mask;
  }


}
